package cn.springcloud.book.config;


import cn.springcloud.book.common.AuthExceptionEntryPoint;
import cn.springcloud.book.handler.CustomAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author: yukong
 * @date: 2018/10/11 11:12
 * @description: oauth2资源服务器配置
 */
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;


    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }


    @Bean
    public TokenStore jwtTokenStore() {
        //资源服务器会自动配置这个过滤器-根据tokenStore获取token，然后去校验tokende有效性
        OAuth2AuthenticationProcessingFilter oAuth2AuthenticationProcessingFilter = new OAuth2AuthenticationProcessingFilter();
        return new JwtTokenStore(jwtTokenConverter());
    }

    @Bean
    protected JwtAccessTokenConverter jwtTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("springcloud123");
        return converter;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config = http.authorizeRequests();
        // iframe 处理
        config.and().headers().frameOptions().disable();
        config.antMatchers("/auth/**").permitAll();
        config.antMatchers("/client-a/**").permitAll();
        config.antMatchers("/client/**").permitAll();


        config.antMatchers("/swagger-ui.html").permitAll();
        config.antMatchers("/swagger-resources/**").permitAll();
        config.antMatchers("/*/v2/api-docs").permitAll();
        config.antMatchers("/webjars/**").permitAll();

        config.antMatchers("/doc.html").permitAll();
        config.antMatchers("/refresh/**").permitAll();
        config.antMatchers("/**/*.css").permitAll();

//        ignoreUrlPropertiesConfig.getUrls().forEach(e -> {
//            config.antMatchers(e).permitAll();
//        });
        // 前后分离 先发出options 放行
        config.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated();

    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(jwtTokenStore())
                .accessDeniedHandler(customAccessDeniedHandler)
                .authenticationEntryPoint(new AuthExceptionEntryPoint());
    }
}
